--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
tests/backend/test_rrc_room_keys.py dev (af76f09d) Text, 15.59 KB
T8b949e# SPDX-License-Identifier: 0BSD
T8b949e"""Tests for RRC +k room key crypto, storage, hub checks, and API."""
Tff7b72from T7ee787__future__ Tff7b72import Te6edf3annotations
Tff7b72import T7ee787json
Tff7b72from T7ee787unittestT7ee787.T7ee787mock Tff7b72import Te6edf3MagicMock
Tff7b72import T7ee787pytest
Tff7b72from T7ee787hypothesis Tff7b72import Te6edf3givenTb4b4b4, Te6edf3settings
Tff7b72from T7ee787hypothesis Tff7b72import Te6edf3strategies Tff7b72as Te6edf3st
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787rrc Tff7b72import Te6edf3protocol Tff7b72as Te6edf3proto
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787rrcT7ee787.T7ee787manager Tff7b72import Te6edf3RRCHubTb4b4b4, Te6edf3RRCManager
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787rrcT7ee787.T7ee787room_key_crypto Tff7b72import Tb4b4b4(
Te6edf3decrypt_room_keyTb4b4b4,
Te6edf3encrypt_room_keyTb4b4b4,
Te6edf3room_keys_equalTb4b4b4,
Tb4b4b4)
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787rrcT7ee787.T7ee787server Tff7b72import Te6edf3RRCHubServerTb4b4b4, Te6edf3_Session
Te6edf3HUB_HASH_HEX Tff7b72= Ta5d6ff"Ta5d6ff00112233445566778899aabbccddeeffTa5d6ff"
Te6edf3HUB_HASH Tff7b72= Tffa657bytesTff7b72.Td2a8fffromhexTb4b4b4(Te6edf3HUB_HASH_HEXTb4b4b4)
Te6edf3PRIVATE_A Tff7b72= Ta5d6ffbTa5d6ff"Ta5d6ffidentity-private-key-aaaaTa5d6ff"
Te6edf3PRIVATE_B Tff7b72= Ta5d6ffbTa5d6ff"Ta5d6ffidentity-private-key-bbbbTa5d6ff"
Tff7b72class T56d364_IdentityTb4b4b4:
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3hash_bytesTb4b4b4, Te6edf3private_keyTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffhash Tff7b72= Te6edf3hash_bytes
Tff7b72selfTff7b72.Td2a8ff_private_key Tff7b72= Te6edf3private_key
Tff7b72def Td2a8ffget_private_keyTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ff_private_key
Tff7b72class T56d364_FakeLinkTb4b4b4:
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3identityTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_identity Tff7b72= Te6edf3identity
Tff7b72def Td2a8ffget_remote_identityTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ff_identity
Tff7b72def Td2a8ff_find_handlerTb4b4b4(Te6edf3appTb4b4b4, Te6edf3pathTb4b4b4, Te6edf3methodTb4b4b4)Tb4b4b4:
Tff7b72for Te6edf3route Tff7b72in Te6edf3appTff7b72.Td2a8ffget_routesTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3routeTff7b72.Td2a8ffpath Tff7b72== Te6edf3path Tff7b72and Te6edf3routeTff7b72.Td2a8ffmethod Tff7b72== Te6edf3methodTb4b4b4:
Tff7b72return Te6edf3routeTff7b72.Td2a8ffhandler
Tff7b72return Tff7b72None
Tff7b72def Td2a8ff_make_requestTb4b4b4(Te6edf3json_bodyTff7b72=Tff7b72NoneTb4b4b4, Te6edf3match_infoTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Te6edf3request Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)
Tff7b72async Tff7b72def Td2a8ff_jsonTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3json_body Tff7b72if Te6edf3json_body Tff7b72is Tff7b72not Tff7b72None Tff7b72else Tb4b4b4{Tb4b4b4}
Te6edf3requestTff7b72.Td2a8ffjson Tff7b72= Te6edf3_json
Te6edf3requestTff7b72.Td2a8ffmatch_info Tff7b72= Te6edf3match_info Tff7b72or Tb4b4b4{Tb4b4b4}
Te6edf3requestTff7b72.Td2a8ffquery Tff7b72= Tb4b4b4{Tb4b4b4}
Tff7b72return Te6edf3request
Tff7b72def Td2a8fftest_encrypt_decrypt_roundtripTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3nonceTb4b4b4, Te6edf3ciphertext Tff7b72= Te6edf3encrypt_room_keyTb4b4b4(Te6edf3PRIVATE_ATb4b4b4, Ta5d6ff"Ta5d6ff secret-key Ta5d6ff"Tb4b4b4)
Tff7b72assert Te6edf3decrypt_room_keyTb4b4b4(Te6edf3PRIVATE_ATb4b4b4, Te6edf3nonceTb4b4b4, Te6edf3ciphertextTb4b4b4) Tff7b72== Ta5d6ff"Ta5d6ffsecret-keyTa5d6ff"
Tff7b72assert Ta5d6ffbTa5d6ff"Ta5d6ffsecret-keyTa5d6ff" Tff7b72not Tff7b72in Te6edf3ciphertext
Tff7b72assert Ta5d6ffbTa5d6ff"Ta5d6ffsecretTa5d6ff" Tff7b72not Tff7b72in Te6edf3ciphertext
Tff7b72def Td2a8fftest_decrypt_fails_for_other_identityTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3nonceTb4b4b4, Te6edf3ciphertext Tff7b72= Te6edf3encrypt_room_keyTb4b4b4(Te6edf3PRIVATE_ATb4b4b4, Ta5d6ff"Ta5d6ffsecret-keyTa5d6ff"Tb4b4b4)
Tff7b72with Te6edf3pytestTff7b72.Td2a8ffraisesTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3decrypt_room_keyTb4b4b4(Te6edf3PRIVATE_BTb4b4b4, Te6edf3nonceTb4b4b4, Te6edf3ciphertextTb4b4b4)
Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffparametrizeTb4b4b4(
Ta5d6ff"Ta5d6ffbadTa5d6ff"Tb4b4b4,
Tb4b4b4[
Ta5d6ff"Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ff Ta5d6ff"Tb4b4b4,
Tff7b72NoneTb4b4b4,
T79c0ff123Tb4b4b4,
Ta5d6ff"Ta5d6ffxTa5d6ff" Tff7b72* T79c0ff300Tb4b4b4,
Tb4b4b4]Tb4b4b4,
Tb4b4b4)
Tff7b72def Td2a8fftest_encrypt_rejects_invalid_keysTb4b4b4(Te6edf3badTb4b4b4)Tb4b4b4:
Tff7b72with Te6edf3pytestTff7b72.Td2a8ffraisesTb4b4b4(Tb4b4b4(Tf85149TypeErrorTb4b4b4, Tf85149ValueErrorTb4b4b4)Tb4b4b4)Tb4b4b4:
Te6edf3encrypt_room_keyTb4b4b4(Te6edf3PRIVATE_ATb4b4b4, Te6edf3badTb4b4b4)
Tf0883e@givenTb4b4b4(
Te6edf3leftTff7b72=Te6edf3stTff7b72.Td2a8fftextTb4b4b4(Te6edf3min_sizeTff7b72=T79c0ff1Tb4b4b4, Te6edf3max_sizeTff7b72=T79c0ff32Tb4b4b4)Tff7b72.Td2a8fffilterTb4b4b4(Tff7b72lambda Te6edf3sTb4b4b4: Tffa657boolTb4b4b4(Te6edf3sTff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4)Tb4b4b4,
Te6edf3pad_lTff7b72=Te6edf3stTff7b72.Td2a8ffintegersTb4b4b4(Te6edf3min_valueTff7b72=T79c0ff0Tb4b4b4, Te6edf3max_valueTff7b72=T79c0ff3Tb4b4b4)Tb4b4b4,
Te6edf3pad_rTff7b72=Te6edf3stTff7b72.Td2a8ffintegersTb4b4b4(Te6edf3min_valueTff7b72=T79c0ff0Tb4b4b4, Te6edf3max_valueTff7b72=T79c0ff3Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tf0883e@settingsTb4b4b4(Te6edf3max_examplesTff7b72=T79c0ff40Tb4b4b4, Te6edf3deadlineTff7b72=Tff7b72NoneTb4b4b4)
Tff7b72def Td2a8fftest_property_room_keys_equal_stripsTb4b4b4(Te6edf3leftTb4b4b4, Te6edf3pad_lTb4b4b4, Te6edf3pad_rTb4b4b4)Tb4b4b4:
Te6edf3expected Tff7b72= Te6edf3leftTff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Te6edf3provided Tff7b72= Tb4b4b4(Ta5d6ff"Ta5d6ff Ta5d6ff" Tff7b72* Te6edf3pad_lTb4b4b4) Tff7b72+ Te6edf3expected Tff7b72+ Tb4b4b4(Ta5d6ff"Ta5d6ff Ta5d6ff" Tff7b72* Te6edf3pad_rTb4b4b4)
Tff7b72assert Te6edf3room_keys_equalTb4b4b4(Te6edf3providedTb4b4b4, Te6edf3expectedTb4b4b4) Tff7b72is Tff7b72True
Tff7b72assert Te6edf3room_keys_equalTb4b4b4(Te6edf3expected Tff7b72+ Ta5d6ff"Ta5d6ffxTa5d6ff"Tb4b4b4, Te6edf3expectedTb4b4b4) Tff7b72is Tff7b72False
Tff7b72assert Te6edf3room_keys_equalTb4b4b4(Tff7b72NoneTb4b4b4, Te6edf3expectedTb4b4b4) Tff7b72is Tff7b72False
Tff7b72def Td2a8fftest_dao_upsert_get_deleteTb4b4b4(Te6edf3dbTb4b4b4)Tb4b4b4:
Te6edf3nonceTb4b4b4, Te6edf3ciphertext Tff7b72= Te6edf3encrypt_room_keyTb4b4b4(Te6edf3PRIVATE_ATb4b4b4, Ta5d6ff"Ta5d6ffalphaTa5d6ff"Tb4b4b4)
Te6edf3dbTff7b72.Td2a8ffrrc_room_keysTff7b72.Td2a8ffupsertTb4b4b4(Te6edf3HUB_HASH_HEXTb4b4b4, Ta5d6ff"Ta5d6ffrrc.hubTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fflobbyTa5d6ff"Tb4b4b4, Te6edf3nonceTb4b4b4, Te6edf3ciphertextTb4b4b4)
Te6edf3row Tff7b72= Te6edf3dbTff7b72.Td2a8ffrrc_room_keysTff7b72.Td2a8ffgetTb4b4b4(Te6edf3HUB_HASH_HEXTb4b4b4, Ta5d6ff"Ta5d6ffrrc.hubTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fflobbyTa5d6ff"Tb4b4b4)
Tff7b72assert Te6edf3row Tff7b72is Tff7b72not Tff7b72None
Tff7b72assert Te6edf3decrypt_room_keyTb4b4b4(Te6edf3PRIVATE_ATb4b4b4, Te6edf3rowTb4b4b4[Ta5d6ff"Ta5d6ffnonceTa5d6ff"Tb4b4b4]Tb4b4b4, Te6edf3rowTb4b4b4[Ta5d6ff"Ta5d6ffciphertextTa5d6ff"Tb4b4b4]Tb4b4b4) Tff7b72== Ta5d6ff"Ta5d6ffalphaTa5d6ff"
Te6edf3nonce2Tb4b4b4, Te6edf3ciphertext2 Tff7b72= Te6edf3encrypt_room_keyTb4b4b4(Te6edf3PRIVATE_ATb4b4b4, Ta5d6ff"Ta5d6ffbetaTa5d6ff"Tb4b4b4)
Te6edf3dbTff7b72.Td2a8ffrrc_room_keysTff7b72.Td2a8ffupsertTb4b4b4(Te6edf3HUB_HASH_HEXTb4b4b4, Ta5d6ff"Ta5d6ffrrc.hubTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fflobbyTa5d6ff"Tb4b4b4, Te6edf3nonce2Tb4b4b4, Te6edf3ciphertext2Tb4b4b4)
Te6edf3row2 Tff7b72= Te6edf3dbTff7b72.Td2a8ffrrc_room_keysTff7b72.Td2a8ffgetTb4b4b4(Te6edf3HUB_HASH_HEXTb4b4b4, Ta5d6ff"Ta5d6ffrrc.hubTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fflobbyTa5d6ff"Tb4b4b4)
Tff7b72assert Te6edf3decrypt_room_keyTb4b4b4(Te6edf3PRIVATE_ATb4b4b4, Te6edf3row2Tb4b4b4[Ta5d6ff"Ta5d6ffnonceTa5d6ff"Tb4b4b4]Tb4b4b4, Te6edf3row2Tb4b4b4[Ta5d6ff"Ta5d6ffciphertextTa5d6ff"Tb4b4b4]Tb4b4b4) Tff7b72== Ta5d6ff"Ta5d6ffbetaTa5d6ff"
Te6edf3listed Tff7b72= Te6edf3dbTff7b72.Td2a8ffrrc_room_keysTff7b72.Td2a8fflist_for_hubTb4b4b4(Te6edf3HUB_HASH_HEXTb4b4b4, Ta5d6ff"Ta5d6ffrrc.hubTa5d6ff"Tb4b4b4)
Tff7b72assert Tffa657lenTb4b4b4(Te6edf3listedTb4b4b4) Tff7b72== T79c0ff1
Tff7b72assert Ta5d6ff"Ta5d6ffciphertextTa5d6ff" Tff7b72not Tff7b72in Te6edf3listedTb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8ffkeysTb4b4b4(Tb4b4b4) Tff7b72or Te6edf3listedTb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffciphertextTa5d6ff"Tb4b4b4) Tff7b72is Tff7b72None
Tff7b72assert Te6edf3dbTff7b72.Td2a8ffrrc_room_keysTff7b72.Td2a8ffdeleteTb4b4b4(Te6edf3HUB_HASH_HEXTb4b4b4, Ta5d6ff"Ta5d6ffrrc.hubTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fflobbyTa5d6ff"Tb4b4b4) Tff7b72== T79c0ff1
Tff7b72assert Te6edf3dbTff7b72.Td2a8ffrrc_room_keysTff7b72.Td2a8ffgetTb4b4b4(Te6edf3HUB_HASH_HEXTb4b4b4, Ta5d6ff"Ta5d6ffrrc.hubTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fflobbyTa5d6ff"Tb4b4b4) Tff7b72is Tff7b72None
Tff7b72def Td2a8fftest_manager_remember_get_forgetTb4b4b4(Te6edf3dbTb4b4b4, Te6edf3tmp_pathTb4b4b4)Tb4b4b4:
Te6edf3identity Tff7b72= Te6edf3_IdentityTb4b4b4(Ta5d6ffbTa5d6ff"Tffea00\x11Ta5d6ff" Tff7b72* T79c0ff16Tb4b4b4, Te6edf3PRIVATE_ATb4b4b4)
Te6edf3manager Tff7b72= Te6edf3RRCManagerTb4b4b4(Te6edf3identityTb4b4b4, Tffa657strTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4, Te6edf3databaseTff7b72=Te6edf3dbTb4b4b4)
Te6edf3hub Tff7b72= Te6edf3managerTff7b72.Td2a8ffadd_hubTb4b4b4(Te6edf3HUB_HASHTb4b4b4, Te6edf3nameTff7b72=Ta5d6ff"Ta5d6ffHubTa5d6ff"Tb4b4b4)
Te6edf3managerTff7b72.Td2a8ffremember_room_keyTb4b4b4(Te6edf3hubTb4b4b4, Ta5d6ff"Ta5d6ffLobbyTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffcorrect-horseTa5d6ff"Tb4b4b4)
Tff7b72assert Te6edf3managerTff7b72.Td2a8ffget_room_keyTb4b4b4(Te6edf3hubTb4b4b4, Ta5d6ff"Ta5d6fflobbyTa5d6ff"Tb4b4b4) Tff7b72== Ta5d6ff"Ta5d6ffcorrect-horseTa5d6ff"
Tff7b72assert Te6edf3managerTff7b72.Td2a8ffhas_stored_room_keyTb4b4b4(Te6edf3hubTb4b4b4, Ta5d6ff"Ta5d6fflobbyTa5d6ff"Tb4b4b4) Tff7b72is Tff7b72True
Te6edf3keys Tff7b72= Te6edf3managerTff7b72.Td2a8fflist_stored_room_keysTb4b4b4(Te6edf3hubTb4b4b4)
Tff7b72assert Te6edf3keys Tff7b72== Tb4b4b4[
Tb4b4b4{
Ta5d6ff"Ta5d6ffhub_hashTa5d6ff"Tb4b4b4: Te6edf3HUB_HASH_HEXTb4b4b4,
Ta5d6ff"Ta5d6ffdest_nameTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffrrc.hubTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffroomTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fflobbyTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffupdated_atTa5d6ff"Tb4b4b4: Te6edf3keysTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[Ta5d6ff"Ta5d6ffupdated_atTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4]
Tff7b72assert Ta5d6ff"Ta5d6ffkeyTa5d6ff" Tff7b72not Tff7b72in Te6edf3keysTb4b4b4[T79c0ff0Tb4b4b4]
Tff7b72assert Te6edf3managerTff7b72.Td2a8ffforget_room_keyTb4b4b4(Te6edf3hubTb4b4b4, Ta5d6ff"Ta5d6fflobbyTa5d6ff"Tb4b4b4) Tff7b72== T79c0ff1
Tff7b72assert Te6edf3managerTff7b72.Td2a8ffget_room_keyTb4b4b4(Te6edf3hubTb4b4b4, Ta5d6ff"Ta5d6fflobbyTa5d6ff"Tb4b4b4) Tff7b72is Tff7b72None
Tff7b72def Td2a8fftest_manager_wrong_identity_returns_noneTb4b4b4(Te6edf3dbTb4b4b4, Te6edf3tmp_pathTb4b4b4)Tb4b4b4:
Te6edf3manager_a Tff7b72= Te6edf3RRCManagerTb4b4b4(
Te6edf3_IdentityTb4b4b4(Ta5d6ffbTa5d6ff"Tffea00\x11Ta5d6ff" Tff7b72* T79c0ff16Tb4b4b4, Te6edf3PRIVATE_ATb4b4b4)Tb4b4b4, Tffa657strTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4, Te6edf3databaseTff7b72=Te6edf3db
Tb4b4b4)
Te6edf3hub Tff7b72= Te6edf3manager_aTff7b72.Td2a8ffadd_hubTb4b4b4(Te6edf3HUB_HASHTb4b4b4)
Te6edf3manager_aTff7b72.Td2a8ffremember_room_keyTb4b4b4(Te6edf3hubTb4b4b4, Ta5d6ff"Ta5d6fflobbyTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffsecretTa5d6ff"Tb4b4b4)
Te6edf3manager_b Tff7b72= Te6edf3RRCManagerTb4b4b4(
Te6edf3_IdentityTb4b4b4(Ta5d6ffbTa5d6ff"Tffea00\x22Ta5d6ff" Tff7b72* T79c0ff16Tb4b4b4, Te6edf3PRIVATE_BTb4b4b4)Tb4b4b4, Tffa657strTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4, Te6edf3databaseTff7b72=Te6edf3db
Tb4b4b4)
Te6edf3hub_b Tff7b72= Te6edf3manager_bTff7b72.Td2a8ffadd_hubTb4b4b4(Te6edf3HUB_HASHTb4b4b4)
Tff7b72assert Te6edf3manager_bTff7b72.Td2a8ffget_room_keyTb4b4b4(Te6edf3hub_bTb4b4b4, Ta5d6ff"Ta5d6fflobbyTa5d6ff"Tb4b4b4) Tff7b72is Tff7b72None
Tff7b72assert Te6edf3manager_bTff7b72.Td2a8ffhas_stored_room_keyTb4b4b4(Te6edf3hub_bTb4b4b4, Ta5d6ff"Ta5d6fflobbyTa5d6ff"Tb4b4b4) Tff7b72is Tff7b72True
Tff7b72def Td2a8fftest_bad_key_error_detectorTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72assert Te6edf3RRCManagerTff7b72.Td2a8ffis_bad_key_errorTb4b4b4(Ta5d6ff"Ta5d6ffbad key (+k)Ta5d6ff"Tb4b4b4) Tff7b72is Tff7b72True
Tff7b72assert Te6edf3RRCManagerTff7b72.Td2a8ffis_bad_key_errorTb4b4b4(Ta5d6ff"Ta5d6ffERROR: Bad Key (+K)Ta5d6ff"Tb4b4b4) Tff7b72is Tff7b72True
Tff7b72assert Te6edf3RRCManagerTff7b72.Td2a8ffis_bad_key_errorTb4b4b4(Ta5d6ff"Ta5d6ffinvite-only (+i)Ta5d6ff"Tb4b4b4) Tff7b72is Tff7b72False
Tff7b72assert Te6edf3RRCManagerTff7b72.Td2a8ffis_bad_key_errorTb4b4b4(Ta5d6ff"Ta5d6fffailed: enable +k firstTa5d6ff"Tb4b4b4) Tff7b72is Tff7b72False
Tff7b72assert Te6edf3RRCManagerTff7b72.Td2a8ffis_bad_key_errorTb4b4b4(Ta5d6ff"Ta5d6ff+kTa5d6ff"Tb4b4b4) Tff7b72is Tff7b72False
Tff7b72assert Te6edf3RRCManagerTff7b72.Td2a8ffis_bad_key_errorTb4b4b4(Tff7b72NoneTb4b4b4) Tff7b72is Tff7b72False
Tff7b72def Td2a8fftest_redact_mode_plus_k_for_historyTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72assert Tb4b4b4(
Te6edf3RRCHubTff7b72.Td2a8ff_redact_command_for_historyTb4b4b4(Ta5d6ff"Ta5d6ff/mode vault +k supersecretTa5d6ff"Tb4b4b4)
Tff7b72== Ta5d6ff"Ta5d6ff/mode vault +k ***Ta5d6ff"
Tb4b4b4)
Tff7b72assert Te6edf3RRCHubTff7b72.Td2a8ff_redact_command_for_historyTb4b4b4(Ta5d6ff"Ta5d6ff/who lobbyTa5d6ff"Tb4b4b4) Tff7b72== Ta5d6ff"Ta5d6ff/who lobbyTa5d6ff"
Tff7b72assert Te6edf3RRCHubTff7b72.Td2a8ff_redact_command_for_historyTb4b4b4(Ta5d6ff"Ta5d6ff/mode vault -kTa5d6ff"Tb4b4b4) Tff7b72== Ta5d6ff"Ta5d6ff/mode vault -kTa5d6ff"
Tff7b72def Td2a8fftest_handle_error_forgets_bad_keyTb4b4b4(Te6edf3dbTb4b4b4, Te6edf3tmp_pathTb4b4b4)Tb4b4b4:
Te6edf3identity Tff7b72= Te6edf3_IdentityTb4b4b4(Ta5d6ffbTa5d6ff"Tffea00\x11Ta5d6ff" Tff7b72* T79c0ff16Tb4b4b4, Te6edf3PRIVATE_ATb4b4b4)
Te6edf3manager Tff7b72= Te6edf3RRCManagerTb4b4b4(Te6edf3identityTb4b4b4, Tffa657strTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4, Te6edf3databaseTff7b72=Te6edf3dbTb4b4b4)
Te6edf3hub Tff7b72= Te6edf3managerTff7b72.Td2a8ffadd_hubTb4b4b4(Te6edf3HUB_HASHTb4b4b4)
Te6edf3managerTff7b72.Td2a8ffremember_room_keyTb4b4b4(Te6edf3hubTb4b4b4, Ta5d6ff"Ta5d6fflobbyTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffwrongTa5d6ff"Tb4b4b4)
Tff7b72with Te6edf3hubTff7b72.Td2a8ff_lockTb4b4b4:
Te6edf3hubTff7b72.Td2a8ff_pending_joinsTff7b72.Td2a8ffaddTb4b4b4(Ta5d6ff"Ta5d6fflobbyTa5d6ff"Tb4b4b4)
Te6edf3hubTff7b72.Td2a8ffroomsTff7b72.Td2a8ffaddTb4b4b4(Ta5d6ff"Ta5d6fflobbyTa5d6ff"Tb4b4b4)
Te6edf3hubTff7b72.Td2a8ff_handle_errorTb4b4b4(
Te6edf3protoTff7b72.Td2a8ffmake_envelopeTb4b4b4(
Te6edf3protoTff7b72.Td2a8ffT_ERRORTb4b4b4,
Te6edf3srcTff7b72=Te6edf3HUB_HASHTb4b4b4,
Te6edf3roomTff7b72=Ta5d6ff"Ta5d6fflobbyTa5d6ff"Tb4b4b4,
Te6edf3bodyTff7b72=Ta5d6ff"Ta5d6ffbad key (+k)Ta5d6ff"Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3managerTff7b72.Td2a8ffget_room_keyTb4b4b4(Te6edf3hubTb4b4b4, Ta5d6ff"Ta5d6fflobbyTa5d6ff"Tb4b4b4) Tff7b72is Tff7b72None
Tff7b72assert Ta5d6ff"Ta5d6fflobbyTa5d6ff" Tff7b72not Tff7b72in Te6edf3hubTff7b72.Td2a8ffrooms
Tff7b72def Td2a8fftest_welcome_rejoin_uses_stored_keyTb4b4b4(Te6edf3dbTb4b4b4, Te6edf3tmp_pathTb4b4b4, Te6edf3monkeypatchTb4b4b4)Tb4b4b4:
Te6edf3identity Tff7b72= Te6edf3_IdentityTb4b4b4(Ta5d6ffbTa5d6ff"Tffea00\x11Ta5d6ff" Tff7b72* T79c0ff16Tb4b4b4, Te6edf3PRIVATE_ATb4b4b4)
Te6edf3manager Tff7b72= Te6edf3RRCManagerTb4b4b4(Te6edf3identityTb4b4b4, Tffa657strTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4, Te6edf3databaseTff7b72=Te6edf3dbTb4b4b4)
Te6edf3hub Tff7b72= Te6edf3managerTff7b72.Td2a8ffadd_hubTb4b4b4(Te6edf3HUB_HASHTb4b4b4)
Te6edf3hubTff7b72.Td2a8ffadd_roomTb4b4b4(Ta5d6ff"Ta5d6ffsecretTa5d6ff"Tb4b4b4)
Te6edf3managerTff7b72.Td2a8ffremember_room_keyTb4b4b4(Te6edf3hubTb4b4b4, Ta5d6ff"Ta5d6ffsecretTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffhunter2Ta5d6ff"Tb4b4b4)
Te6edf3seen Tff7b72= Tb4b4b4{Tb4b4b4}
Tff7b72def Td2a8ff_fake_joinTb4b4b4(Te6edf3roomTb4b4b4, Te6edf3keyTff7b72=Tff7b72NoneTb4b4b4, Te6edf3silentTff7b72=Tff7b72FalseTb4b4b4)Tb4b4b4:
Te6edf3seenTb4b4b4[Ta5d6ff"Ta5d6ffroomTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3room
Te6edf3seenTb4b4b4[Ta5d6ff"Ta5d6ffkeyTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3key
Te6edf3seenTb4b4b4[Ta5d6ff"Ta5d6ffsilentTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3silent
Te6edf3monkeypatchTff7b72.Td2a8ffsetattrTb4b4b4(Te6edf3hubTb4b4b4, Ta5d6ff"Ta5d6ffjoin_roomTa5d6ff"Tb4b4b4, Te6edf3_fake_joinTb4b4b4)
Te6edf3managerTff7b72.Td2a8ff_on_welcomeTb4b4b4(Te6edf3hubTb4b4b4)
Tff7b72assert Te6edf3seen Tff7b72== Tb4b4b4{Ta5d6ff"Ta5d6ffroomTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffsecretTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffkeyTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffhunter2Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffsilentTa5d6ff"Tb4b4b4: Tff7b72TrueTb4b4b4}
Tff7b72def Td2a8fftest_hub_rejects_wrong_key_and_accepts_correctTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3owner Tff7b72= Te6edf3_IdentityTb4b4b4(Te6edf3HUB_HASHTb4b4b4, Te6edf3PRIVATE_ATb4b4b4)
Te6edf3server Tff7b72= Te6edf3RRCHubServerTb4b4b4(Te6edf3MagicMockTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3ownerTb4b4b4, Te6edf3nameTff7b72=Ta5d6ff"Ta5d6ffKeyed HubTa5d6ff"Tb4b4b4)
Te6edf3serverTff7b72.Td2a8ffregister_roomTb4b4b4(Ta5d6ff"Ta5d6ffvaultTa5d6ff"Tb4b4b4, Te6edf3keyTff7b72=Ta5d6ff"Ta5d6ffcorrectTa5d6ff"Tb4b4b4)
Te6edf3cfg Tff7b72= Te6edf3serverTff7b72.Td2a8ffroomsTff7b72.Td2a8ffroom_config_for_apiTb4b4b4(Ta5d6ff"Ta5d6ffvaultTa5d6ff"Tb4b4b4)
Tff7b72assert Te6edf3cfgTb4b4b4[Ta5d6ff"Ta5d6ffhas_keyTa5d6ff"Tb4b4b4] Tff7b72is Tff7b72True
Tff7b72assert Ta5d6ff"Ta5d6ffkeyTa5d6ff" Tff7b72not Tff7b72in Te6edf3cfg
Te6edf3peer Tff7b72= Te6edf3_IdentityTb4b4b4(Ta5d6ffbTa5d6ff"Tffea00\xaaTa5d6ff" Tff7b72* T79c0ff16Tb4b4b4, Ta5d6ffbTa5d6ff"Ta5d6ffpeer-keyTa5d6ff"Tb4b4b4)
Te6edf3link Tff7b72= Te6edf3_FakeLinkTb4b4b4(Te6edf3peerTb4b4b4)
Te6edf3sess Tff7b72= Te6edf3_SessionTb4b4b4(Tb4b4b4)
Te6edf3sessTff7b72.Td2a8ffpeer Tff7b72= Te6edf3peerTff7b72.Td2a8ffhash
Te6edf3sessTff7b72.Td2a8ffnick Tff7b72= Ta5d6ff"Ta5d6ffaliceTa5d6ff"
Te6edf3sessTff7b72.Td2a8ffwelcomed Tff7b72= Tff7b72True
Te6edf3serverTff7b72.Td2a8ff_sessionsTb4b4b4[Te6edf3linkTb4b4b4] Tff7b72= Te6edf3sess
Te6edf3bad_out Tff7b72= Tb4b4b4[Tb4b4b4]
Te6edf3serverTff7b72.Td2a8ff_routeTb4b4b4(
Te6edf3linkTb4b4b4,
Te6edf3sessTb4b4b4,
Te6edf3protoTff7b72.Td2a8ffmake_envelopeTb4b4b4(Te6edf3protoTff7b72.Td2a8ffT_JOINTb4b4b4, Te6edf3srcTff7b72=Te6edf3peerTff7b72.Td2a8ffhashTb4b4b4, Te6edf3roomTff7b72=Ta5d6ff"Ta5d6ffvaultTa5d6ff"Tb4b4b4, Te6edf3bodyTff7b72=Ta5d6ff"Ta5d6ffwrongTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3bad_outTb4b4b4,
Tb4b4b4)
Te6edf3bad_envs Tff7b72= Tb4b4b4[Te6edf3protoTff7b72.Td2a8ffdecodeTb4b4b4(Te6edf3payloadTb4b4b4) Tff7b72for Te6edf3_Tb4b4b4, Te6edf3payload Tff7b72in Te6edf3bad_outTb4b4b4]
Tff7b72assert Tffa657anyTb4b4b4(
Te6edf3eTb4b4b4[Te6edf3protoTff7b72.Td2a8ffK_TTb4b4b4] Tff7b72== Te6edf3protoTff7b72.Td2a8ffT_ERROR Tff7b72and Te6edf3eTb4b4b4[Te6edf3protoTff7b72.Td2a8ffK_BODYTb4b4b4] Tff7b72== Ta5d6ff"Ta5d6ffbad key (+k)Ta5d6ff"
Tff7b72for Te6edf3e Tff7b72in Te6edf3bad_envs
Tb4b4b4)
Tff7b72assert Ta5d6ff"Ta5d6ffvaultTa5d6ff" Tff7b72not Tff7b72in Te6edf3sessTff7b72.Td2a8ffrooms
Tff7b72assert Te6edf3serverTff7b72.Td2a8ffroomsTff7b72.Td2a8ffensure_stateTb4b4b4(Ta5d6ff"Ta5d6ffvaultTa5d6ff"Tb4b4b4)Tff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fffounderTa5d6ff"Tb4b4b4) Tff7b72is Tff7b72None
Te6edf3good_out Tff7b72= Tb4b4b4[Tb4b4b4]
Te6edf3serverTff7b72.Td2a8ff_routeTb4b4b4(
Te6edf3linkTb4b4b4,
Te6edf3sessTb4b4b4,
Te6edf3protoTff7b72.Td2a8ffmake_envelopeTb4b4b4(Te6edf3protoTff7b72.Td2a8ffT_JOINTb4b4b4, Te6edf3srcTff7b72=Te6edf3peerTff7b72.Td2a8ffhashTb4b4b4, Te6edf3roomTff7b72=Ta5d6ff"Ta5d6ffvaultTa5d6ff"Tb4b4b4, Te6edf3bodyTff7b72=Ta5d6ff"Ta5d6ffcorrectTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3good_outTb4b4b4,
Tb4b4b4)
Te6edf3good_envs Tff7b72= Tb4b4b4[Te6edf3protoTff7b72.Td2a8ffdecodeTb4b4b4(Te6edf3payloadTb4b4b4) Tff7b72for Te6edf3_Tb4b4b4, Te6edf3payload Tff7b72in Te6edf3good_outTb4b4b4]
Tff7b72assert Tffa657anyTb4b4b4(Te6edf3eTb4b4b4[Te6edf3protoTff7b72.Td2a8ffK_TTb4b4b4] Tff7b72== Te6edf3protoTff7b72.Td2a8ffT_JOINED Tff7b72for Te6edf3e Tff7b72in Te6edf3good_envsTb4b4b4)
Tff7b72assert Te6edf3serverTff7b72.Td2a8ffroomsTff7b72.Td2a8ffis_room_opTb4b4b4(Ta5d6ff"Ta5d6ffvaultTa5d6ff"Tb4b4b4, Te6edf3peerTff7b72.Td2a8ffhashTb4b4b4) Tff7b72is Tff7b72True
Tff7b72def Td2a8fftest_hub_invite_only_checked_before_founder_promotionTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3owner Tff7b72= Te6edf3_IdentityTb4b4b4(Te6edf3HUB_HASHTb4b4b4, Te6edf3PRIVATE_ATb4b4b4)
Te6edf3server Tff7b72= Te6edf3RRCHubServerTb4b4b4(Te6edf3MagicMockTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3ownerTb4b4b4, Te6edf3nameTff7b72=Ta5d6ff"Ta5d6ffInvite HubTa5d6ff"Tb4b4b4)
Te6edf3serverTff7b72.Td2a8ffregister_roomTb4b4b4(Ta5d6ff"Ta5d6ffprivateTa5d6ff"Tb4b4b4, Te6edf3invite_onlyTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3peer Tff7b72= Te6edf3_IdentityTb4b4b4(Ta5d6ffbTa5d6ff"Tffea00\xbbTa5d6ff" Tff7b72* T79c0ff16Tb4b4b4, Ta5d6ffbTa5d6ff"Ta5d6ffpeer-keyTa5d6ff"Tb4b4b4)
Te6edf3link Tff7b72= Te6edf3_FakeLinkTb4b4b4(Te6edf3peerTb4b4b4)
Te6edf3sess Tff7b72= Te6edf3_SessionTb4b4b4(Tb4b4b4)
Te6edf3sessTff7b72.Td2a8ffpeer Tff7b72= Te6edf3peerTff7b72.Td2a8ffhash
Te6edf3sessTff7b72.Td2a8ffnick Tff7b72= Ta5d6ff"Ta5d6ffbobTa5d6ff"
Te6edf3sessTff7b72.Td2a8ffwelcomed Tff7b72= Tff7b72True
Te6edf3serverTff7b72.Td2a8ff_sessionsTb4b4b4[Te6edf3linkTb4b4b4] Tff7b72= Te6edf3sess
Te6edf3out Tff7b72= Tb4b4b4[Tb4b4b4]
Te6edf3serverTff7b72.Td2a8ff_routeTb4b4b4(
Te6edf3linkTb4b4b4,
Te6edf3sessTb4b4b4,
Te6edf3protoTff7b72.Td2a8ffmake_envelopeTb4b4b4(Te6edf3protoTff7b72.Td2a8ffT_JOINTb4b4b4, Te6edf3srcTff7b72=Te6edf3peerTff7b72.Td2a8ffhashTb4b4b4, Te6edf3roomTff7b72=Ta5d6ff"Ta5d6ffprivateTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3outTb4b4b4,
Tb4b4b4)
Te6edf3envs Tff7b72= Tb4b4b4[Te6edf3protoTff7b72.Td2a8ffdecodeTb4b4b4(Te6edf3payloadTb4b4b4) Tff7b72for Te6edf3_Tb4b4b4, Te6edf3payload Tff7b72in Te6edf3outTb4b4b4]
Tff7b72assert Tffa657anyTb4b4b4(
Te6edf3eTb4b4b4[Te6edf3protoTff7b72.Td2a8ffK_TTb4b4b4] Tff7b72== Te6edf3protoTff7b72.Td2a8ffT_ERROR Tff7b72and Te6edf3eTb4b4b4[Te6edf3protoTff7b72.Td2a8ffK_BODYTb4b4b4] Tff7b72== Ta5d6ff"Ta5d6ffinvite-only (+i)Ta5d6ff"
Tff7b72for Te6edf3e Tff7b72in Te6edf3envs
Tb4b4b4)
Tff7b72assert Te6edf3serverTff7b72.Td2a8ffroomsTff7b72.Td2a8ffensure_stateTb4b4b4(Ta5d6ff"Ta5d6ffprivateTa5d6ff"Tb4b4b4)Tff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fffounderTa5d6ff"Tb4b4b4) Tff7b72is Tff7b72None
Tff7b72def Td2a8fftest_set_room_key_clear_and_persistTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4:
Te6edf3owner Tff7b72= Te6edf3_IdentityTb4b4b4(Te6edf3HUB_HASHTb4b4b4, Te6edf3PRIVATE_ATb4b4b4)
Te6edf3server Tff7b72= Te6edf3RRCHubServerTb4b4b4(Te6edf3MagicMockTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3ownerTb4b4b4, Te6edf3nameTff7b72=Ta5d6ff"Ta5d6ffKeyed HubTa5d6ff"Tb4b4b4)
Te6edf3serverTff7b72.Td2a8ffregister_roomTb4b4b4(Ta5d6ff"Ta5d6ffvaultTa5d6ff"Tb4b4b4, Te6edf3keyTff7b72=Ta5d6ff"Ta5d6ffoneTa5d6ff"Tb4b4b4)
Tff7b72assert Te6edf3serverTff7b72.Td2a8ffroomsTff7b72.Td2a8ffensure_stateTb4b4b4(Ta5d6ff"Ta5d6ffvaultTa5d6ff"Tb4b4b4)Tb4b4b4[Ta5d6ff"Ta5d6ffkeyTa5d6ff"Tb4b4b4] Tff7b72== Ta5d6ff"Ta5d6ffoneTa5d6ff"
Te6edf3serverTff7b72.Td2a8ffset_room_keyTb4b4b4(Ta5d6ff"Ta5d6ffvaultTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fftwoTa5d6ff"Tb4b4b4)
Tff7b72assert Te6edf3serverTff7b72.Td2a8ffroomsTff7b72.Td2a8ffensure_stateTb4b4b4(Ta5d6ff"Ta5d6ffvaultTa5d6ff"Tb4b4b4)Tb4b4b4[Ta5d6ff"Ta5d6ffkeyTa5d6ff"Tb4b4b4] Tff7b72== Ta5d6ff"Ta5d6fftwoTa5d6ff"
Te6edf3serverTff7b72.Td2a8ffset_room_keyTb4b4b4(Ta5d6ff"Ta5d6ffvaultTa5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72assert Tff7b72not Te6edf3serverTff7b72.Td2a8ffroomsTff7b72.Td2a8ffensure_stateTb4b4b4(Ta5d6ff"Ta5d6ffvaultTa5d6ff"Tb4b4b4)Tb4b4b4[Ta5d6ff"Ta5d6ffkeyTa5d6ff"Tb4b4b4]
Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_api_store_list_delete_room_keyTb4b4b4(Te6edf3mock_appTb4b4b4)Tb4b4b4:
Te6edf3post_hub Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3mock_appTb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/rrc/hubsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4)
Tff7b72await Te6edf3post_hubTb4b4b4(Te6edf3_make_requestTb4b4b4(Te6edf3json_bodyTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_hashTa5d6ff"Tb4b4b4: Te6edf3HUB_HASH_HEXTb4b4b4}Tb4b4b4)Tb4b4b4)
Te6edf3put_key Tff7b72= Te6edf3_find_handlerTb4b4b4(
Te6edf3mock_appTb4b4b4,
Ta5d6ff"Ta5d6ff/api/v1/rrc/hubs/Tffd700{hub_hash}Ta5d6ff/rooms/Tffd700{room}Ta5d6ff/keyTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffPUTTa5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3response Tff7b72= Tff7b72await Te6edf3put_keyTb4b4b4(
Te6edf3_make_requestTb4b4b4(
Te6edf3json_bodyTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffkeyTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffsecretTa5d6ff"Tb4b4b4}Tb4b4b4,
Te6edf3match_infoTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_hashTa5d6ff"Tb4b4b4: Te6edf3HUB_HASH_HEXTb4b4b4, Ta5d6ff"Ta5d6ffroomTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fflobbyTa5d6ff"Tb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3responseTff7b72.Td2a8ffstatus Tff7b72== T79c0ff200
Te6edf3body Tff7b72= Te6edf3jsonTff7b72.Td2a8ffloadsTb4b4b4(Te6edf3responseTff7b72.Td2a8ffbodyTb4b4b4)
Tff7b72assert Te6edf3bodyTb4b4b4[Ta5d6ff"Ta5d6ffhas_stored_keyTa5d6ff"Tb4b4b4] Tff7b72is Tff7b72True
Tff7b72assert Ta5d6ff"Ta5d6ffsecretTa5d6ff" Tff7b72not Tff7b72in Te6edf3responseTff7b72.Td2a8ffbodyTff7b72.Td2a8ffdecodeTb4b4b4(Tb4b4b4)
Te6edf3list_keys Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3mock_appTb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/rrc/hubs/Tffd700{hub_hash}Ta5d6ff/room-keysTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffGETTa5d6ff"Tb4b4b4)
Te6edf3listing Tff7b72= Te6edf3jsonTff7b72.Td2a8ffloadsTb4b4b4(
Tb4b4b4(
Tff7b72await Te6edf3list_keysTb4b4b4(
Te6edf3_make_requestTb4b4b4(Te6edf3match_infoTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_hashTa5d6ff"Tb4b4b4: Te6edf3HUB_HASH_HEXTb4b4b4}Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4)Tff7b72.Td2a8ffbodyTb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3listingTb4b4b4[Ta5d6ff"Ta5d6ffkeysTa5d6ff"Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[Ta5d6ff"Ta5d6ffroomTa5d6ff"Tb4b4b4] Tff7b72== Ta5d6ff"Ta5d6fflobbyTa5d6ff"
Tff7b72assert Ta5d6ff"Ta5d6ffkeyTa5d6ff" Tff7b72not Tff7b72in Te6edf3listingTb4b4b4[Ta5d6ff"Ta5d6ffkeysTa5d6ff"Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]
Tff7b72assert Ta5d6ff"Ta5d6ffciphertextTa5d6ff" Tff7b72not Tff7b72in Te6edf3listingTb4b4b4[Ta5d6ff"Ta5d6ffkeysTa5d6ff"Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]
Te6edf3delete_key Tff7b72= Te6edf3_find_handlerTb4b4b4(
Te6edf3mock_appTb4b4b4,
Ta5d6ff"Ta5d6ff/api/v1/rrc/hubs/Tffd700{hub_hash}Ta5d6ff/rooms/Tffd700{room}Ta5d6ff/keyTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffDELETETa5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3deleted Tff7b72= Tff7b72await Te6edf3delete_keyTb4b4b4(
Te6edf3_make_requestTb4b4b4(Te6edf3match_infoTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_hashTa5d6ff"Tb4b4b4: Te6edf3HUB_HASH_HEXTb4b4b4, Ta5d6ff"Ta5d6ffroomTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fflobbyTa5d6ff"Tb4b4b4}Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3deletedTff7b72.Td2a8ffstatus Tff7b72== T79c0ff200
Tff7b72assert Te6edf3jsonTff7b72.Td2a8ffloadsTb4b4b4(Te6edf3deletedTff7b72.Td2a8ffbodyTb4b4b4)Tb4b4b4[Ta5d6ff"Ta5d6ffdeletedTa5d6ff"Tb4b4b4] Tff7b72== T79c0ff1
Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_api_join_offline_remembers_keyTb4b4b4(Te6edf3mock_appTb4b4b4)Tb4b4b4:
Te6edf3post_hub Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3mock_appTb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/rrc/hubsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4)
Tff7b72await Te6edf3post_hubTb4b4b4(Te6edf3_make_requestTb4b4b4(Te6edf3json_bodyTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_hashTa5d6ff"Tb4b4b4: Te6edf3HUB_HASH_HEXTb4b4b4}Tb4b4b4)Tb4b4b4)
Te6edf3join Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3mock_appTb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/rrc/hubs/Tffd700{hub_hash}Ta5d6ff/roomsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4)
Te6edf3response Tff7b72= Tff7b72await Te6edf3joinTb4b4b4(
Te6edf3_make_requestTb4b4b4(
Te6edf3json_bodyTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffroomTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffvaultTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffkeyTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffoffline-secretTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffrememberTa5d6ff"Tb4b4b4: Tff7b72TrueTb4b4b4}Tb4b4b4,
Te6edf3match_infoTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_hashTa5d6ff"Tb4b4b4: Te6edf3HUB_HASH_HEXTb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3responseTff7b72.Td2a8ffstatus Tff7b72== T79c0ff200
Te6edf3data Tff7b72= Te6edf3jsonTff7b72.Td2a8ffloadsTb4b4b4(Te6edf3responseTff7b72.Td2a8ffbodyTb4b4b4)
Tff7b72assert Te6edf3dataTb4b4b4[Ta5d6ff"Ta5d6ffhas_stored_keyTa5d6ff"Tb4b4b4] Tff7b72is Tff7b72True
Tff7b72assert Ta5d6ff"Ta5d6ffoffline-secretTa5d6ff" Tff7b72not Tff7b72in Te6edf3responseTff7b72.Td2a8ffbodyTff7b72.Td2a8ffdecodeTb4b4b4(Tb4b4b4)
Te6edf3hub Tff7b72= Te6edf3mock_appTff7b72.Td2a8ffrrc_managerTff7b72.Td2a8fffind_hubTb4b4b4(Te6edf3HUB_HASHTb4b4b4)
Tff7b72assert Te6edf3mock_appTff7b72.Td2a8ffrrc_managerTff7b72.Td2a8ffget_room_keyTb4b4b4(Te6edf3hubTb4b4b4, Ta5d6ff"Ta5d6ffvaultTa5d6ff"Tb4b4b4) Tff7b72== Ta5d6ff"Ta5d6ffoffline-secretTa5d6ff"
Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_api_join_uses_stored_key_when_connectedTb4b4b4(Te6edf3mock_appTb4b4b4, Te6edf3monkeypatchTb4b4b4)Tb4b4b4:
Te6edf3post_hub Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3mock_appTb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/rrc/hubsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4)
Tff7b72await Te6edf3post_hubTb4b4b4(Te6edf3_make_requestTb4b4b4(Te6edf3json_bodyTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_hashTa5d6ff"Tb4b4b4: Te6edf3HUB_HASH_HEXTb4b4b4}Tb4b4b4)Tb4b4b4)
Te6edf3hub Tff7b72= Te6edf3mock_appTff7b72.Td2a8ffrrc_managerTff7b72.Td2a8fffind_hubTb4b4b4(Te6edf3HUB_HASHTb4b4b4)
Te6edf3mock_appTff7b72.Td2a8ffrrc_managerTff7b72.Td2a8ffremember_room_keyTb4b4b4(Te6edf3hubTb4b4b4, Ta5d6ff"Ta5d6ffvaultTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffstored-secretTa5d6ff"Tb4b4b4)
Tff7b72with Te6edf3hubTff7b72.Td2a8ff_lockTb4b4b4:
Te6edf3hubTff7b72.Td2a8ffstatus Tff7b72= Te6edf3RRCHubTff7b72.Td2a8ffSTATUS_CONNECTED
Te6edf3seen Tff7b72= Tb4b4b4{Tb4b4b4}
Tff7b72def Td2a8ff_fake_joinTb4b4b4(Te6edf3roomTb4b4b4, Te6edf3keyTff7b72=Tff7b72NoneTb4b4b4, Te6edf3silentTff7b72=Tff7b72FalseTb4b4b4)Tb4b4b4:
Te6edf3seenTb4b4b4[Ta5d6ff"Ta5d6ffroomTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3room
Te6edf3seenTb4b4b4[Ta5d6ff"Ta5d6ffkeyTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3key
Te6edf3monkeypatchTff7b72.Td2a8ffsetattrTb4b4b4(Te6edf3hubTb4b4b4, Ta5d6ff"Ta5d6ffjoin_roomTa5d6ff"Tb4b4b4, Te6edf3_fake_joinTb4b4b4)
Te6edf3join Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3mock_appTb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/rrc/hubs/Tffd700{hub_hash}Ta5d6ff/roomsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4)
Te6edf3response Tff7b72= Tff7b72await Te6edf3joinTb4b4b4(
Te6edf3_make_requestTb4b4b4(
Te6edf3json_bodyTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffroomTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffvaultTa5d6ff"Tb4b4b4}Tb4b4b4,
Te6edf3match_infoTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_hashTa5d6ff"Tb4b4b4: Te6edf3HUB_HASH_HEXTb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3responseTff7b72.Td2a8ffstatus Tff7b72== T79c0ff200
Tff7b72assert Te6edf3seen Tff7b72== Tb4b4b4{Ta5d6ff"Ta5d6ffroomTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffvaultTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffkeyTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffstored-secretTa5d6ff"Tb4b4b4}
Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_api_put_key_rejects_emptyTb4b4b4(Te6edf3mock_appTb4b4b4)Tb4b4b4:
Te6edf3post_hub Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3mock_appTb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/rrc/hubsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4)
Tff7b72await Te6edf3post_hubTb4b4b4(Te6edf3_make_requestTb4b4b4(Te6edf3json_bodyTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_hashTa5d6ff"Tb4b4b4: Te6edf3HUB_HASH_HEXTb4b4b4}Tb4b4b4)Tb4b4b4)
Te6edf3put_key Tff7b72= Te6edf3_find_handlerTb4b4b4(
Te6edf3mock_appTb4b4b4,
Ta5d6ff"Ta5d6ff/api/v1/rrc/hubs/Tffd700{hub_hash}Ta5d6ff/rooms/Tffd700{room}Ta5d6ff/keyTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffPUTTa5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3response Tff7b72= Tff7b72await Te6edf3put_keyTb4b4b4(
Te6edf3_make_requestTb4b4b4(
Te6edf3json_bodyTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffkeyTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ff Ta5d6ff"Tb4b4b4}Tb4b4b4,
Te6edf3match_infoTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_hashTa5d6ff"Tb4b4b4: Te6edf3HUB_HASH_HEXTb4b4b4, Ta5d6ff"Ta5d6ffroomTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fflobbyTa5d6ff"Tb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3responseTff7b72.Td2a8ffstatus Tff7b72== T79c0ff400
Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_api_join_remember_false_skips_storageTb4b4b4(Te6edf3mock_appTb4b4b4)Tb4b4b4:
Te6edf3post_hub Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3mock_appTb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/rrc/hubsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4)
Tff7b72await Te6edf3post_hubTb4b4b4(Te6edf3_make_requestTb4b4b4(Te6edf3json_bodyTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_hashTa5d6ff"Tb4b4b4: Te6edf3HUB_HASH_HEXTb4b4b4}Tb4b4b4)Tb4b4b4)
Te6edf3join Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3mock_appTb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/rrc/hubs/Tffd700{hub_hash}Ta5d6ff/roomsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4)
Te6edf3response Tff7b72= Tff7b72await Te6edf3joinTb4b4b4(
Te6edf3_make_requestTb4b4b4(
Te6edf3json_bodyTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffroomTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffvaultTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffkeyTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffephemeralTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffrememberTa5d6ff"Tb4b4b4: Tff7b72FalseTb4b4b4}Tb4b4b4,
Te6edf3match_infoTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_hashTa5d6ff"Tb4b4b4: Te6edf3HUB_HASH_HEXTb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3responseTff7b72.Td2a8ffstatus Tff7b72== T79c0ff200
Te6edf3data Tff7b72= Te6edf3jsonTff7b72.Td2a8ffloadsTb4b4b4(Te6edf3responseTff7b72.Td2a8ffbodyTb4b4b4)
Tff7b72assert Te6edf3dataTb4b4b4[Ta5d6ff"Ta5d6ffhas_stored_keyTa5d6ff"Tb4b4b4] Tff7b72is Tff7b72False
Te6edf3hub Tff7b72= Te6edf3mock_appTff7b72.Td2a8ffrrc_managerTff7b72.Td2a8fffind_hubTb4b4b4(Te6edf3HUB_HASHTb4b4b4)
Tff7b72assert Te6edf3mock_appTff7b72.Td2a8ffrrc_managerTff7b72.Td2a8ffget_room_keyTb4b4b4(Te6edf3hubTb4b4b4, Ta5d6ff"Ta5d6ffvaultTa5d6ff"Tb4b4b4) Tff7b72is Tff7b72None
Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_host_api_set_and_clear_room_keyTb4b4b4(Te6edf3mock_appTb4b4b4)Tb4b4b4:
Te6edf3create Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3mock_appTb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/rrc/serversTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4)
Te6edf3created Tff7b72= Tff7b72await Te6edf3createTb4b4b4(
Te6edf3_make_requestTb4b4b4(Te6edf3json_bodyTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffHost HubTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffenabledTa5d6ff"Tb4b4b4: Tff7b72FalseTb4b4b4}Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3createdTff7b72.Td2a8ffstatus Tff7b72== T79c0ff200
Te6edf3hub_id Tff7b72= Te6edf3jsonTff7b72.Td2a8ffloadsTb4b4b4(Te6edf3createdTff7b72.Td2a8ffbodyTb4b4b4)Tb4b4b4[Ta5d6ff"Ta5d6ffhubTa5d6ff"Tb4b4b4]Tb4b4b4[Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4]
Te6edf3add_room Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3mock_appTb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/rrc/servers/Tffd700{hub_id}Ta5d6ff/roomsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4)
Te6edf3room_resp Tff7b72= Tff7b72await Te6edf3add_roomTb4b4b4(
Te6edf3_make_requestTb4b4b4(
Te6edf3json_bodyTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffvaultTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffkeyTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffinitialTa5d6ff"Tb4b4b4}Tb4b4b4,
Te6edf3match_infoTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_idTa5d6ff"Tb4b4b4: Te6edf3hub_idTb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3room_respTff7b72.Td2a8ffstatus Tff7b72== T79c0ff200
Te6edf3rooms Tff7b72= Te6edf3jsonTff7b72.Td2a8ffloadsTb4b4b4(Te6edf3room_respTff7b72.Td2a8ffbodyTb4b4b4)Tb4b4b4[Ta5d6ff"Ta5d6ffhubTa5d6ff"Tb4b4b4]Tb4b4b4[Ta5d6ff"Ta5d6ffroomsTa5d6ff"Tb4b4b4]
Te6edf3vault Tff7b72= Tffa657nextTb4b4b4(Te6edf3r Tff7b72for Te6edf3r Tff7b72in Te6edf3rooms Tff7b72if Te6edf3rTb4b4b4[Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4] Tff7b72== Ta5d6ff"Ta5d6ffvaultTa5d6ff"Tb4b4b4)
Tff7b72assert Te6edf3vaultTb4b4b4[Ta5d6ff"Ta5d6ffhas_keyTa5d6ff"Tb4b4b4] Tff7b72is Tff7b72True
Tff7b72assert Ta5d6ff"Ta5d6ffkeyTa5d6ff" Tff7b72not Tff7b72in Te6edf3vault
Tff7b72assert Ta5d6ffbTa5d6ff"Ta5d6ffinitialTa5d6ff" Tff7b72not Tff7b72in Te6edf3room_respTff7b72.Td2a8ffbody
Te6edf3set_key Tff7b72= Te6edf3_find_handlerTb4b4b4(
Te6edf3mock_appTb4b4b4,
Ta5d6ff"Ta5d6ff/api/v1/rrc/servers/Tffd700{hub_id}Ta5d6ff/rooms/Tffd700{room}Ta5d6ff/keyTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffPUTTa5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3cleared Tff7b72= Tff7b72await Te6edf3set_keyTb4b4b4(
Te6edf3_make_requestTb4b4b4(
Te6edf3json_bodyTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffkeyTa5d6ff"Tb4b4b4: Tff7b72NoneTb4b4b4}Tb4b4b4,
Te6edf3match_infoTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhub_idTa5d6ff"Tb4b4b4: Te6edf3hub_idTb4b4b4, Ta5d6ff"Ta5d6ffroomTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffvaultTa5d6ff"Tb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3clearedTff7b72.Td2a8ffstatus Tff7b72== T79c0ff200
Te6edf3rooms2 Tff7b72= Te6edf3jsonTff7b72.Td2a8ffloadsTb4b4b4(Te6edf3clearedTff7b72.Td2a8ffbodyTb4b4b4)Tb4b4b4[Ta5d6ff"Ta5d6ffhubTa5d6ff"Tb4b4b4]Tb4b4b4[Ta5d6ff"Ta5d6ffroomsTa5d6ff"Tb4b4b4]
Te6edf3vault2 Tff7b72= Tffa657nextTb4b4b4(Te6edf3r Tff7b72for Te6edf3r Tff7b72in Te6edf3rooms2 Tff7b72if Te6edf3rTb4b4b4[Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4] Tff7b72== Ta5d6ff"Ta5d6ffvaultTa5d6ff"Tb4b4b4)
Tff7b72assert Te6edf3vault2Tb4b4b4[Ta5d6ff"Ta5d6ffhas_keyTa5d6ff"Tb4b4b4] Tff7b72is Tff7b72False
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────